#include<iostream>
using namespace std;

//front不存放内容，队头元素位于array[(front+1)%capacity]
template<class T>
class arrayQueue{
private:
    int capacity;//队列最大容量
    int size;//队列当前长度
    T*array;
    int front;//队头
    int rear;//队尾
public:
    arrayQueue(int&cap){
        this->capacity=cap;
        size=front=rear=0;
        array=new T[this->capacity];
    };
    ~arrayQueue(){
        delete[]this->array;
    };

    bool isEmpty()const{
        return this->size==0;
    }
    int getSize(){
        return this->size;
    }
    void push(T&e);
    void pop();
    T&getFront()const;
    T&getRear()const;
};

template<class T>
void arrayQueue<T>::push(T&e){
    if(size==capacity-1){
        cout<<"The queue is full."<<endl;
        return;
    }//自定义异常也可
    rear=(rear+1)%capacity;
    array[rear]=e;
    size++;
    /*
    如果考虑队列扩充的情况，代码如下：
    if(size!=capacity){
        rear=(rear+1)%capacity;
        array[rear]=e;
        size++;
        return;
    }
    T*newArray=new T[capacity*2];
    int start=(front+1)%capacity;
    //判断是否形成了环
    //如果形成，复制逻辑为：
    //1.将(front+1,capacity-1)的元素复制到newArray的起始位置
    //2.将(0,rear)的元素复制到newArray紧挨着之前元素的后续位置
    if(start<2)
        copy(array+start,array+start+capacity-1,newArray);
    else{
        copy(array+start,array+start+capacity,newArray);
        copy(array,array+rear+1,newArray+capacity-start);
    }
    front=capacity*2-1;//新队列的末尾
    rear=capacity-2;//rear向后移动了capacity-rear-2个位置，最终位置为rear+capacity-rear-2=capacity-2
    capacity*=2;
    delete array;
    array=newArray;
    */
}

template<class T>
void arrayQueue<T>::pop(){
    if(size==0){
        cout<<"The queue is empty."<<endl;
        return;
    }//自定义异常也可
    front=(front+1)%capacity;
    size--;
}

template<class T>
T& arrayQueue<T>::getFront()const{
    if(size==0){
        throw 0;//自定义异常也可
    }
    return array[(front+1)%capacity];
}

template<class T>
T& arrayQueue<T>::getRear()const{
    if(size==0){
        throw 0;//自定义异常也可
    }
    return array[rear];
}

int main(){
    int l=5;
    arrayQueue<int>q(l);
    int*ptr=new int();

    *ptr=1;
    q.push(*ptr);
    cout<<"Front is: "<<q.getFront()<<" Rear is: "<<q.getRear()<<endl;

    *ptr=2;
    q.push(*ptr);
    cout<<"Front is: "<<q.getFront()<<" Rear is: "<<q.getRear()<<endl;

    *ptr=3;
    q.push(*ptr);
    cout<<"Front is: "<<q.getFront()<<" Rear is: "<<q.getRear()<<endl;

    *ptr=4;
    q.push(*ptr);
    cout<<"Front is: "<<q.getFront()<<" Rear is: "<<q.getRear()<<endl;

    *ptr=5;
    q.push(*ptr);
    cout<<"Front is: "<<q.getFront()<<" Rear is: "<<q.getRear()<<endl;
    
    delete ptr;
    return 0;
}